package com.nova.android.tvlauncher.ui.fragment.atv

import android.os.Bundle
import android.os.Handler
import androidx.leanback.widget.BaseGridView
import androidx.leanback.widget.HorizontalGridView
import androidx.lifecycle.lifecycleScope
import io.github.lib_autorun.ext.isNetworkAvailable
import com.nova.android.tvlauncher.AppCache
import com.nova.android.tvlauncher.BuildConfig
import com.nova.android.tvlauncher.R
import com.nova.android.tvlauncher.bean.atv_bean.HomeParentDto
import com.nova.android.tvlauncher.constants.ConstantsAtv
import com.nova.android.tvlauncher.databinding.FragmentHomeListAtvBinding
import com.nova.android.tvlauncher.ext.getFilteredChannelsEnhanced
import com.nova.android.tvlauncher.ext.saveHomeParentDto
import com.nova.android.tvlauncher.net.UrlManager
import com.nova.android.tvlauncher.ui.adapter.atv.HomeListAtvAdapter
import com.nova.android.tvlauncher.utils.TvRepository
import io.github.lib_autorun.net.NetworkHelper
import io.github.lib_autorun.net.enum.RequestMethod
import com.nova.android.tvlauncher.bean.atv_bean.FavoriteAppRemoteDto
import com.nova.android.tvlauncher.bean.atv_bean.HomeInfoDto
import com.nova.android.tvlauncher.bean.atv_bean.HomeProgramDto
import com.nova.android.tvlauncher.constants.ConstantsAtv.NET_CONNECT_CHANGE
import com.nova.android.tvlauncher.ui.adapter.atv.HomeListChannelDataAtvAdapter.curPosition
import com.shudong.lib_base.ext.appContext
import com_github_lib_base.base.BaseVMFragment
import com_github_lib_base.base.BaseViewModel
import com_github_lib_base.bean.FavoriteApp
import com_github_lib_base.ext.dimenValue
import com_github_lib_base.ext.getInstalledApps
import com_github_lib_base.ext.rv.addModels
import com_github_lib_base.ext.rv.models
import com_github_lib_base.ext.rv.removeModelAt
import com_github_lib_base.ext.rv.setup
import com_github_lib_base.ext.stringValue
import com_github_lib_base.ext.toApp
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import observeLiveEvent
import kotlin.collections.map

class HomeListAtvFragment : BaseVMFragment<FragmentHomeListAtvBinding, BaseViewModel>() {

    val homeParentDtoList: MutableList<Any> = mutableListOf()

    fun reqGetFocus() {
        lifecycleScope.launch {
            delay(100)
            mBind.rvHome.requestFocus()
        }

    }


    override fun initView() {
        val isFocus = (parentFragment?.parentFragment as MainATVFragment).isFirstFocus
        if (isFocus) {
            mBind.rvHome.apply {
                post {
                    requestFocus()
                    (parentFragment?.parentFragment as MainATVFragment).setVoiceFocus(true)
                    (parentFragment as HomeAtvFragment).setBannerfocuable()
                    (parentFragment?.parentFragment as MainATVFragment).isFirstFocus = false
                }
            }
        } else {
            (parentFragment as HomeAtvFragment).setBannerfocuable()
        }

        getFavoriteApps()

        val apps = AppCache.favoriteAppList.toMutableList()

        if (apps.isEmpty()) {

            try {
                val launcherItems = AppCache.configLocalDto?.defalutFavorites

                launcherItems?.let {
                    syncFavoriteApps(it, true)?.let {
                        apps.addAll(it)
                    }
                }

            } catch (e: Exception) {
            }


        }

        val addName = com.nova.lib_lang.R.string.main_home_txt_2.stringValue()
        apps.add(FavoriteApp("", addName, "", "", "", -1, true))


        saveHomeParentDto()
        val channelList = getFilteredChannelsEnhanced()
        // channelList.updateChannelList()
        val title = com.nova.lib_lang.R.string.main_home_txt_1.stringValue()
        homeParentDtoList.add(HomeParentDto(title, apps = apps))
        //val homeProgramDto = HomeProgramDto(programTitle = "123", programDesc = "3232", programCover = "https://img1.baidu.com/it/u=3273686700,440353769&fm=253&fmt=auto&app=138&f=JPEG?w=750&h=500")
        /*homeParentDtoList.add(
            HomeParentDto(
                "Youtube",
                1,
                "",
                recommondInfoDtoList = listOf(homeProgramDto,homeProgramDto,homeProgramDto,homeProgramDto,homeProgramDto,homeProgramDto)
            )
        )*/

        channelList.forEach {
            homeParentDtoList.add(
                HomeParentDto(
                    it.channelName.toString(),
                    it.channelId ?: 0,
                    it.packageName ?: "",
                    recommondInfoDtoList = it.programList
                )
            )


        }
        homeParentDtoList.add("2")


        mBind.rvHome.setWindowAlignment(BaseGridView.WINDOW_ALIGN_LOW_EDGE);
        mBind.rvHome.setWindowAlignmentOffset(com.codeZeng.lib_dimen.R.dimen.qb_px_50.dimenValue());
        mBind.rvHome.setWindowAlignmentOffsetPercent(0f);
        mBind.rvHome.setItemAlignmentOffsetPercent(0f);
        //mBind.rvHome.setItemViewCacheSize(100)
        mBind.rvHome.setup(homeParentDtoList) {
            addType(HomeParentDto::class, R.layout.item_app_parent_atv)
            addType(String::class, R.layout.item_home_footer_atv)
            onBind {
                HomeListAtvAdapter.bindData(this, mBind.rvHome)
            }

        }


        /*val count = 100
        mBind.rvHome.post {
            val adapter = mBind.rvHome.adapter ?: return@post
            val safeCount = minOf(count, adapter.itemCount)
            adapter.notifyItemRangeChanged(0, safeCount)
        }*/
        //mBind.rvHome.itemAnimator = null

        mBind.rvHome.setOnChildSelectedListener { _, _, position, _ ->
            positionChangeJob?.cancel() // 取消旧的延迟任务
            positionChangeJob = lifecycleScope.launch {
                delay(POSITION_DELAY)
                curPosition = position
                if (position != lastFocusPosition) {
                    if (position == 0) {
                        (parentFragment as HomeAtvFragment).showTopView()
                        //handler.removeCallbacksAndMessages(null)
                        // handler.postDelayedUnique({
                        (parentFragment as? HomeAtvFragment)?.setListFragmentFullHeight(false)
                        // }, 300)

                    } else {
                        (parentFragment as HomeAtvFragment).hideTopView()
                        (parentFragment as? HomeAtvFragment)?.setListFragmentFullHeight(true, false)
                    }
                    lastFocusPosition = position
                }
            }

        }

    }

    private var positionChangeJob: Job? = null
    private val POSITION_DELAY = 100L // 延迟 100ms 确保最后状态


    override fun initObserver() {
        observeLiveEvent<FavoriteApp>(ConstantsAtv.REFRESH_FAVORITE_APPS) {
            mBind.rvHome.apply {
                post {

                    val rvHori =
                        mBind.rvHome.getChildAt(0).findViewById<HorizontalGridView>(R.id.rv_horizontal)
                    val position = rvHori.models.size - 1
                    (homeParentDtoList.get(0) as HomeParentDto).apps?.add(rvHori.models.size - 1,it)

                    rvHori.addModels(listOf(it), index = position)
                }

                /*postDelayed({
                    rvHori.requestFocus()
                    rvHori.layoutManager?.findViewByPosition(position)?.requestFocus()
                }, 500)*/
            }
        }

        observeLiveEvent<FavoriteApp>(ConstantsAtv.REMOVE_FAVORITE_APPS) { appInfo ->
            mBind.rvHome.apply {

                post {
                    val rvHori =
                        mBind.rvHome.getChildAt(0).findViewById<HorizontalGridView>(R.id.rv_horizontal)
                    val list = rvHori.models as MutableList<FavoriteApp>
                    val position = list.indexOfFirst { it.packageName == appInfo.packageName }

                    (homeParentDtoList.get(0) as HomeParentDto).apps?.removeAt(position)
                    rvHori.removeModelAt(position)
                }

                /* postDelayed({
                     rvHori.layoutManager?.findViewByPosition(0)?.requestFocus()
                 }, 500)*/
            }
        }

        observeLiveEvent<Pair<Boolean, Long>>(ConstantsAtv.UPDATE_HOME_ITEM) {

            val (isShowData, channelId) = it
            if (isShowData) {
                //Log.e("zeng12345", "initObserver: 当前准备显示数据", )
                val list = AppCache.homeParentList
                list.forEach {

                    if (it.channelId == channelId) {
                        //Log.e("zeng12345", "initObserver: 调用显示数据---${channelId}----${it}", )
                        mBind.rvHome.addModels(listOf(it), index = mBind.rvHome.models.size - 1)
                    }


                }
            } else {
                //Log.e("zeng12345", "initObserver: 当前准备移除数据", )
                val list = mBind.rvHome.models as MutableList<*>
                for (i in list.size - 1 downTo 0) {
                    if (list[i] is HomeParentDto) {
                        val bean = list[i] as HomeParentDto
                        if (bean.channelId == channelId) {
                            //Log.e("zeng12345", "initObserver: 调用移除数据", )
                            mBind.rvHome.removeModelAt(i)

                        }
                    }

                }
            }
        }

        observeLiveEvent<Boolean>(ConstantsAtv.REFRESH_CHANNEL_LIST) {
            // Log.e("zeng12345", "当前的本地数量---${AppCache.homeParentList.size}----${TvRepository.getChannelData().size}", )
            (parentFragment as HomeAtvFragment).loadBanner()
            if (AppCache.homeParentList.size != TvRepository.getChannelData().size) {
                homeParentDtoList.clear()
                val apps = AppCache.favoriteAppList.toMutableList()
                val addName = com.nova.lib_lang.R.string.main_home_txt_2.stringValue()
                apps.add(FavoriteApp("", addName, "", "", "", -1, true))


                saveHomeParentDto()
                val channelList = getFilteredChannelsEnhanced()
                //Log.e("zeng12345", "initView: 过滤之后的集合是：---${channelList}", )
                //channelList.updateChannelList()
                val title = com.nova.lib_lang.R.string.main_home_txt_1.stringValue()
                homeParentDtoList.add(HomeParentDto(title, apps = apps))

                channelList.forEach {
                    homeParentDtoList.add(
                        HomeParentDto(
                            it.channelName.toString(),
                            it.channelId ?: 0,
                            it.packageName ?: "",
                            recommondInfoDtoList = it.programList
                        )
                    )
                }
                homeParentDtoList.add("2")
                mBind.rvHome.models = homeParentDtoList
            }

            if (!isServerDataLoadSuccess&&!isReqing) getFavoriteApps()
        }

        observeLiveEvent<Boolean>(NET_CONNECT_CHANGE) { isConnected ->
            if (isConnected && wasDisconnected) {
                //getHomeData()
                wasDisconnected = false
            } else if (!isConnected) {
                wasDisconnected = true
            }
        }


    }

    private var wasDisconnected = false
    var isServerDataLoadSuccess = false
    var isReqing = false


    private fun getFavoriteApps() {
        lifecycleScope.launch {
            while (true) {
                delay(300)
                if (appContext.isNetworkAvailable()) {
                    if (!isServerDataLoadSuccess&&!isReqing) {
                        isReqing = true
                        NetworkHelper.makeRequest(
                            UrlManager.FAV_APPS,
                            RequestMethod.POST,
                            mapOf(
                                "req_id" to 0,
                                "channel" to BuildConfig.CHANNEL,
                                "lang" to "en",
                                "launch_type" to 1,
                                "req_from" to 1,
                            ),
                        ) { dto: List<FavoriteAppRemoteDto>?, error: Throwable? ->
                            if (error == null) {
                                dto?.let { syncFavoriteApps(it) }

                            } else {
                                mBind.rvHome.apply {
                                    post {
                                        requestFocus()
                                    }
                                }
                            }
                            getHomeInfo()
                        }
                        cancel()
                    }
                }
                delay(3500)
            }
        }

    }

    private fun getHomeInfo() {
        NetworkHelper.makeRequest(
            UrlManager.HOME_INFO,
            RequestMethod.POST,
            mapOf(
                "req_id" to 0,
                "channel" to BuildConfig.CHANNEL,
                "launch_type" to 0,
            ),
        ) { dto: HomeInfoDto?, error: Throwable? ->
            isReqing = false
            if (error == null) {
                isServerDataLoadSuccess = true
                dto?.movies?.let {
                    val serverParentDtoList: MutableList<Any> = mutableListOf()
                    it.forEach { movy ->
                        val homeParentDto = HomeParentDto(movy.name.toString())
                        val items = mutableListOf<HomeProgramDto>()
                        movy.datas?.forEach {
                            items.add(
                                HomeProgramDto(
                                    programCover = it.imageUrl, adId = it.adId,
                                    adUrl = it.adUrl, isAd = it.isAd, intentUrl = it.url
                                )
                            )
                        }
                        homeParentDto.packageName =
                            movy.packageNames?.get(0)?.packageName.toString()
                        homeParentDto.recommondInfoDtoList = items
                        serverParentDtoList.add(homeParentDto)
                    }
                    mBind.rvHome.addModels(
                        serverParentDtoList,
                        index = mBind.rvHome.models.size - 1
                    )
                }

            } else {

            }
        }
    }


    // 同步收藏列表
    fun syncFavoriteApps(
        remotePackageNames: List<FavoriteAppRemoteDto>,
        isAdd: Boolean = false
    ): MutableList<FavoriteApp>? {
        val packageNames: List<String> = remotePackageNames.map { it.package_name ?: "" }
        // 获取本地收藏列表
        val favoriteAppList = AppCache.favoriteAppList.toMutableList()

        // 获取已安装的应用信息
        val installedApps = appContext.getInstalledApps()
        val installedPackageNames = installedApps.map { it.activityInfo.packageName }.toSet()

        // 1. 如果收藏列表为空，直接添加所有符合条件的远程包名应用
        if (favoriteAppList.isEmpty()) {
            val newFavorites = packageNames
                .filter { packageName -> installedPackageNames.contains(packageName) }
                .mapNotNull { packageName ->
                    installedApps.find { it.activityInfo.packageName == packageName }
                        ?.toApp(appContext.packageManager)
                        ?.apply {
                            // 赋值 isAd, adId, adUrl
                            val remoteApp =
                                remotePackageNames.find { it.package_name == packageName }
                            this.isAd = remoteApp?.isAd ?: false
                            this.adId = remoteApp?.adId ?: ""
                            this.adUrl = remoteApp?.adUrl ?: ""
                        }
                }
                .map { it.copy() } // 标记为新添加
            favoriteAppList.addAll(newFavorites)
        } else {
            // 1. 将后台返回的包名中已安装但不在收藏列表的应用添加到收藏列表
            val newFavorites = packageNames
                .filter { packageName ->
                    installedPackageNames.contains(packageName) && // 本地已安装
                            favoriteAppList.none { it.packageName == packageName } // 不在收藏列表
                }
                .mapNotNull { packageName ->
                    // 找到对应的 ResolveInfo
                    installedApps.find { it.activityInfo.packageName == packageName }
                        ?.toApp(appContext.packageManager)
                        ?.apply {
                            // 赋值 isAd, adId, adUrl
                            val remoteApp =
                                remotePackageNames.find { it.package_name == packageName }
                            this.isAd = remoteApp?.isAd ?: false
                            this.adId = remoteApp?.adId ?: ""
                            this.adUrl = remoteApp?.adUrl ?: ""
                        }
                }
                .map { it.copy() }.toMutableList() // 标记为新添加

            favoriteAppList.addAll(newFavorites)

            // 2. 将已在收藏列表且在后台返回包名中的应用移到列表前面，并更新 isAd, adId, adUrl
            val reorderedList = mutableListOf<FavoriteApp>()
            packageNames.forEach { packageName ->
                favoriteAppList.find { it.packageName == packageName }?.let { app ->
                    // 更新 isAd, adId, adUrl
                    val remoteApp = remotePackageNames.find { it.package_name == packageName }
                    app.isAd = remoteApp?.isAd ?: false
                    app.adId = remoteApp?.adId ?: ""
                    app.adUrl = remoteApp?.adUrl ?: ""
                    reorderedList.add(app)
                }
            }

            // 再添加剩余的收藏应用（不在后台返回的包名中）
            favoriteAppList.forEach { app ->
                if (!reorderedList.contains(app)) {
                    reorderedList.add(app)
                }
            }

            if (reorderedList == favoriteAppList) return null
            // 更新收藏列表
            favoriteAppList.clear()
            favoriteAppList.addAll(reorderedList)
        }

        favoriteAppList.forEach { it.isAdd = false }
        AppCache.favoriteAppList = favoriteAppList
        if (!isAdd) {
            val addName = com.nova.lib_lang.R.string.main_home_txt_2.stringValue()
            favoriteAppList.add(FavoriteApp("", addName, "", "", "", -1, true))
            (mBind.rvHome.models[0] as HomeParentDto).apps = favoriteAppList
            mBind.rvHome.adapter?.notifyItemChanged(0)
            mBind.rvHome.apply {
                postDelayed({
                    requestFocus()
                }, 100)
            }
        }
        return favoriteAppList

    }


    private var lastFocusPosition = -1
    private var curPosition = -1

    companion object {

        @JvmStatic
        fun newInstance() =
            HomeListAtvFragment().apply {
                arguments = Bundle().apply {

                }
            }
    }
}


